﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once
#include "GcmpUiBase.h"

namespace gcmp {
    
    class TrashBin;
    class GCMP_UIBASE_EXPORT Trash
    {
        friend class TrashBin;

    protected:
        explicit Trash();

    public:
        virtual ~Trash();

        // Discard this trash. This trash does not get deleted, immediately.
        // Instead, wait a time segment to do it. Before delete really, the
        // onAllowToDelete() gets invoked to ask if allowed. If not allowed,
        // wait next time segment.
        void discard();

        // Return true, if discarded already.
        bool isDiscarded() const { return m_discarded(); }

        template <class TTrash>
        static void deleteLater(gcmp::OwnerPtr< TTrash > && opTrash)
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(
                nullptr != opTrash.get() && !opTrash->isDiscarded(),
                L"An invalid trash!", L"fangkunfk", L"2020-12-20");

            if (auto * pTrash = opTrash.ReleaseOwnership())
                pTrash->discard();
        }

    protected:
        // Give the derived class an opportunity to do something.
        virtual void onDiscarded() = 0;
        virtual bool onAllowToDelete() const = 0;

    private:
        struct {
            friend void Trash::discard();
            bool operator()() const { return m_data; }
        private: bool m_data = false; } m_discarded;
    };
}
